﻿Imports System.IO
Imports System.Runtime.Serialization
Imports System.Reflection
Imports System.Threading
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.Text
Imports System.Security.Cryptography

Public Class GeradorMD5

    Public Shared Function GerarMD5(ByVal _stringNaoCriptografada As String) As String
        Dim strResultado As String = ""
        Dim bytMensagem As Byte() = System.Text.Encoding.Default.GetBytes(_stringNaoCriptografada)
        Dim oMD5Provider As System.Security.Cryptography.MD5CryptoServiceProvider = New System.Security.Cryptography.MD5CryptoServiceProvider()

        'Gera o Hash Code
        Dim bytResultado As Byte() = oMD5Provider.ComputeHash(bytMensagem)

        Dim sb As New StringBuilder()
        For i As Integer = 0 To bytResultado.Length - 1
            sb.Append(bytResultado(i))
        Next
        Return sb.ToString()
    End Function

End Class

Public Class MD5HashGenerator
    'private Object locker = new Object();
    Public Shared locker As [Object] = "locking variable"

    ''' <summary>
    ''' Generates a hashed - key for an instance of a class.
    ''' The hash is a classic MD5 hash (e.g. BF20EB8D2C4901112179BF5D242D996B). So you can distinguish different 
    ''' instances of a class. Because the object is hashed on the internal state, you can also hash it, then send it to
    ''' someone in a serialized way. Your client can then deserialize it and check if it is in
    ''' the same state.
    ''' The method just just estimates that the object implements the ISerializable interface. What's
    ''' needed to save the state or so, is up to the implementer of the interface.
    ''' <b>The method is thread-safe!</b>
    ''' </summary>
    ''' <param name="sourceObject">The object you'd like to have a key out of it.</param>
    ''' <returns>An string representing a MD5 Hashkey corresponding to the object</returns>
    ''' <exception cref="ApplicationException">Will be thrown if the key cannot be generated.</exception>
    Public Shared Function GenerateKey(ByVal sourceObject As [Object]) As [String]
        Dim hashString As [String] = ""

        'Catch unuseful parameter values
        If sourceObject Is Nothing Then
            Throw New ApplicationException("Null as parameter is not allowed")
        Else
            'We determine if the passed object is really serializable.
            Try
                Dim implementedInterface As Type = sourceObject.[GetType]().GetInterface("ISerializable")
                If implementedInterface Is Nothing Then
                    Throw New ApplicationException("Object is not serializable")
                Else
                    'Now we begin to do the real work.
                    hashString = ComputeHash(ObjectToByteArray(sourceObject))
                    Return hashString
                End If
            Catch ame As AmbiguousMatchException
                Throw New ApplicationException("Could not definitly decide if object is serializable.")
            End Try
        End If
    End Function

    ''' <summary>
    ''' Converts an object to an array of bytes. This array is used to hash the object.
    ''' </summary>
    ''' <param name="objectToSerialize">Just an object</param>
    ''' <returns>A byte - array representation of the object.</returns>
    ''' <exception cref="SerializationException">Is thrown if something went wrong during serialization.</exception>
    Private Shared Function ObjectToByteArray(ByVal objectToSerialize As [Object]) As Byte()
        Dim fs As New MemoryStream()
        Dim formatter As New BinaryFormatter()
        Try
            'Here's the core functionality! One Line!
            'To be thread-safe we lock the object
            SyncLock locker
                formatter.Serialize(fs, objectToSerialize)
                fs.Close()
            End SyncLock
            Return fs.ToArray()
        Catch se As SerializationException
            Throw se
        Finally
            fs.Close()
        End Try
    End Function

    ''' <summary>
    ''' Generates the hashcode of an given byte-array. The byte-array can be an object. Then the
    ''' method "hashes" this object. The hash can then be used e.g. to identify the object.
    ''' </summary>
    ''' <param name="objectAsBytes">bytearray representation of an object.</param>
    ''' <returns>The MD5 hash of the object as a string or null if it couldn't be generated.</returns>
    Public Shared Function ComputeHash(ByVal objectAsBytes As Byte()) As String
        Dim md5 As Security.Cryptography.MD5 = New MD5CryptoServiceProvider()
        Dim result As Byte() = md5.ComputeHash(objectAsBytes)

        ' Build the final string by converting each byte
        ' into hex and appending it to a StringBuilder
        Dim sb As New StringBuilder()
        For i As Integer = 0 To result.Length - 1
            sb.Append(result(i).ToString("X2"))
        Next

        ' And return it
        Return sb.ToString()
    End Function
End Class

Public Class GerarSymmetricAlgorithm

    Private Shared encryptionAlgorithm As SymmetricAlgorithm = GerarSymmetricAlgorithm()

    Public Shared Function GerarSymmetricAlgorithm() As SymmetricAlgorithm
        Dim symmetricAlgorithm = RijndaelManaged.Create()
        symmetricAlgorithm.IV = New [Byte]() {56, 151, 249, 160, 183, 47, _
                                                5, 42, 90, 5, 207, 241, _
                                                11, 166, 166, 173}
        symmetricAlgorithm.Key = New [Byte]() {214, 145, 104, 41, 148, 129, _
                                                139, 16, 224, 38, 40, 15, _
                                                5, 254, 217, 193, 146, 43, _
                                                187, 174, 132, 181, 220, 211, _
                                                228, 181, 153, 173, 239, 194, _
                                                45, 253}
        Return symmetricAlgorithm
    End Function

    Public Shared Function EncryptString(ByVal _parametroNaoCriptografado As String) As String
        Dim clearTextBytes As Byte() = Encoding.UTF8.GetBytes(_parametroNaoCriptografado)
        Dim encrypted As Byte() = encryptionAlgorithm.CreateEncryptor().TransformFinalBlock(clearTextBytes, 0, clearTextBytes.Length)
        Return Convert.ToBase64String(encrypted)
    End Function

    Public Shared Function DecryptString(ByVal _parametroCriptografado As String) As String
        Dim encryptedBytes As Byte() = Convert.FromBase64String(_parametroCriptografado)
        Dim decryptedBytes As Byte() = encryptionAlgorithm.CreateDecryptor().TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length)
        Return Encoding.UTF8.GetString(decryptedBytes)
    End Function

End Class